<?php
/**
 * The BBCode-Class of the LDCMS3
 * 
 * 
 * @param none
 * @author Dennis Franke <dennis@franke-s.de>
 * @package LD-CMS2
 */
class BBCode {
	private static $bbcode = NULL;
	
	private $tags = array('search' => array(), 'replace' => array());
	
	/**
	 * Konstruktor
	 *
	 * @param bool $custom
	 */
	private function __construct() {}
	private function __clone() {}
	
	public static function getInstance() {
		if(self::$bbcode === null) {
			self::$bbcode = new BBCode;
			self::$bbcode->initBBCode();
		}
		return self::$bbcode;	
	}
	
	
	/**
	 * Init BBCode
	 */
	public function initBBCode() {
		$query = DB::getInstance()->query("
			SELECT
				id,
				bbcodeInput,
				bbcodeReplace
			FROM
				".Tables::$bbcodeTbl."");
		while($b = DB::getInstance()->fetchAssoc($query)) {
			$this->add_Tag($b['id'],$b['bbcodeInput'],$b['bbcodeReplace']);
		}
	}
	
	
	 
	 /**
	  * Macht regul�ren ausdruck.
	  *
	  * @param string $string
	  * @return string $string
	  */
	 private function prepare_Pattern($string) {
         $string = addcslashes($string,'\'\\/,^$.[]|()?*+{}');
         $string = preg_replace("/%[a-z]/", "(.*)", $string);
         $string = '/'.$string.'/isUe';
         return $string;
     }
	 
	 /**
	  * Bereitet HTML-Code vor.
	  *
	  * @param string $string
	  * @param string $placeholders
	  * @return string $string
	  */
	 private function prepare_html_Output($string, $placeholders) {
         $i = 0;
         //$string = str_replace("'", "\'", $string);
         $string = str_replace(array("'", "%\'"), array("\'", "'"), $string);
         $string = "'".$string."'";
         foreach ($placeholders as $index => $plc) {
		 	
             if ($plc !== null) {           	
                 $string = str_replace($index, "'.".$plc."('\$".($i+1)."').'", $string);
             } else {
                 $string = str_replace($index, "\$".($i+1), $string);
             }
             $i++;
         }
         return $string;
     }
	 
	 /**
	  * Pr�fft funktionen auf Valit�t.
	  *
	  * @param string $name Funktionsname
	  * @return bool
	  */
	 private function is_valid_function_array(&$name) {
         $all_valid = true;
         foreach ($name as $plc => $function) {
             $valid = true;
             if (preg_match("/^%[a-z]/", $plc)) {
                 if (stristr($function, '$this->') !== false) {
                     $function_array = explode('->', $function);
                     if (!is_callable(array($this, $function_array[1]))) $valid = false;    
                 } elseif (strstr($function, '::') !== false) {
                     $function_array = explode('::', $function);
                     if (!is_callable(array("$function_array[0]", $function_array[1]))) $valid = false;
                 } else {
                     if (!function_exists($function)) $valid = false;
                 }
                 if (!$valid) {
                     $all_valid = false;
                     $name[$plc] = $name[$plc].' - ERROR: method/function is not callable';
                 }
             }
         }
		 
         return $all_valid;
     }
	 
	 /**
	  * Tags hinzuf�gen.
	  *
	  * @param string $name Name des tags.
	  * @param string $bbcode bbcode.
	  * @param string $htmlcode htmlcode.
	  * @param array $callback_functions
	  */
	 public function add_Tag($name, $bbcode, $htmlcode, $callback_functions = array()) {
         $placeholders  = array();
         $place_holders = array();
         if (count($callback_functions) > 0 && !$this->is_valid_function_array($callback_functions))
             throw new Exception (__FILE__.":".__LINE__."  :  ".print_r($callback_functions, true));
             
          preg_match_all("/%[a-z]/", $bbcode, $place_holders);
		  
         foreach ($place_holders[0] as $plc) {
		
             $placeholders[$plc]    = (isset($callback_functions[$plc])) ? $callback_functions[$plc] : null;
         }
         $this->tags['search'][$name]  = $this->prepare_Pattern($bbcode);
         $this->tags['replace'][$name] = $this->prepare_html_Output($htmlcode, $placeholders);
     }

	public function delete_Tag($name) {
		unset($this->tags['search'][$name]);
		unset($this->tags['replace'][$name]);
	}
	 
	 /**
	  * Strings Parsen.
	  *
	  * @param string $string
	  * @return string $string
	  */
	 public function parse($string,$parseSpecial = false) {
		if($parseSpecial) {
			BBCode::getInstance()->add_Tag('content', '[content]%c[/content]', '%c',array("%c"=>'$this->prepare_content'));
			BBCode::getInstance()->add_Tag('HTML', '[HTML]%c[/HTML]', '%c',array("%c"=>'$this->prepare_html'));
		}
	 	$old_string = "";
	 
	 	
	 	// Parse List-Items
	 	$lines = explode("\n",$string);
	 	$openUL = false;
	 	foreach($lines as $key=>$line) {
	 		if(substr($line,0,1) == "*" || substr($line,0,1) == "#") {
	 			$ulTag = "<ul>";
	 			if(substr($line,0,1) == "#") $ulTag = "<ul style='list-style-type:decimal;'>";
	 			if($openUL == false) {
	 				$lines[$key] = $ulTag."<li>".substr($line,1)."</li>";
	 				$openUL = true;
	 			}else{
	 				$lines[$key] = "<li>".substr($line,1)."</li>";
	 			}
	 		}else{
	 			if($openUL == true) {
	 				$lines[$key] = "</ul>".$line;
	 				$openUL = false;
	 			}
	 		}
	 	}
	 	if($openUL) $lines[count($lines)] = "</ul>";
	 	
	 	$string = implode("\n",$lines);
	 	
	 	
		while($old_string != $string)
		{
			$old_string = $string;
			//$string = preg_replace_callback('{\[(\w+)((=)(.+)|())\]((.|\n)*)\[/\1\]}U', 'bbcode_callback', $string);
			$string = preg_replace($this->tags['search'], $this->tags['replace'], $string);
		}
		if($parseSpecial) {
			BBCode::getInstance()->delete_Tag('content');
			BBCode::getInstance()->delete_Tag('HTML');
		}
		
		return $string;      
	 }
	 
	 /**
	  * Bereitet Code vor.
	  *
	  * @param string $text
	  * @return string $text
	  */
	 public function prepare_Code($text) {
		if (isset($_GET['show']) && $_GET['show'] == 'message') {
			$text = str_replace('<br />','',stripslashes(htmlentities($text)));
		} else {
			$text = str_replace('<br />','',stripslashes($text));
		}
		return $text;
	 }
	 
	 /**
	  * Bereitet PHP-Code vor.
	  *
	  * @param string $text
	  * @return string $text
	  */
	 public function prepare_phpCode($text) {
	 	$text = html_entity_decode($text);
		$text = highlight_string($text,true);
		if(isset($_GET['show']) && $_GET['show']=='message') {
			$text = str_replace('<br />','',stripslashes($text));
		} else {
			$text = str_replace('<br />','',$text);
		}
		return $text;
	 }

	/**
	 * Bereitet PHP-Code vor.
	 *
	 * @param string $text
	 * @return string $text
	 */
	public function prepare_content($text) {
		return Content::getInstance()->getContent($text);
	 }
	
	public function prepare_html($text) {
		return htmlspecialchars_decode($text);
	}
	
	
	
    
    /**
     * Enter description here...
     *
     * @param string $s
     * @return unknown
     */
    public static function destroy_bbcode($s) {
        $old_string = '';
        while ($old_string != $s) {
            $old_string = $s;
            $s = preg_replace("=\[([a-zA-Z0-9.\.\/\-\:\?\&\_\=]{1,})\]=i","",$s);
        }   
        return $s;
    }

	 
	 
	 /**
	  * ADMIN ADD BBCODE
	  */
	 public function createBBcode($input,$replace) {
	 	DB::getInstance()->query("
	 		INSERT INTO
	 			".Tables::$bbcodeTbl."
	 		SET
	 			bbcodeInput = '".DB::parseVar($input)."',
	 			bbcodeReplace = '".DB::parseVar($replace)."'");
	 }
	 
	 /**
	  * ADMIN EDIT BBCODE
	  */
	 public function editBBcode($id,$input,$replace) {
	 	if(!is_numeric($id)) exit;
	 	
	 	DB::getInstance()->query("
	 		UPDATE
	 			".Tables::$bbcodeTbl."
	 		SET
	 			bbcodeInput = '".DB::parseVar($input)."',
	 			bbcodeReplace = '".DB::parseVar($replace)."'
	 		WHERE
	 			id = '".$id."'");
	 }
	 
	 /**
	  * ADMIN DELETE BBCODE
	  */
	 public function deleteBBcode($id) {
	 	if(!is_numeric($id)) exit;
	 	
	 	DB::getInstance()->query("
	 		DELETE FROM
	 			".Tables::$bbcodeTbl."
	 		WHERE
	 			id = '".$id."'");
	 }
}

?>